from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from bs4 import BeautifulSoup
from datetime import datetime, timedelta

import copy
import threading
import requests
import logging


logging.disable(logging.CRITICAL)
CALENDER = {"Jan": "1", "Feb": "2", "Mar": "3", "Apr": "4", "May": "5", "Jun": "6", "Jul": "7", "Aug": "8",
            "Sept": "9", "Oct": "10", "Nov": "11", "Dec": "12"}
headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
}


class Match:
    def __init__(self, name: str, platForm: str, startTime: datetime, 
                 lastsTime: timedelta = None, endTime: datetime = None) -> None:
        self.name = name
        self.platForm = platForm
        self.startTime = startTime
        self.lastsTime = lastsTime
        self.endTime = endTime
        if lastsTime == None and startTime and endTime:
            self.lastsTime = self.endTime - self.startTime

    def __str__(self) -> str:
        return f"Start: {self.startTime}\tEnd: {self.endTime}\tLasts: {self.lastsTime}\t" +\
                f"Platform: {self.platForm}\tName: {self.name}"
 

LUOGU_URL = "https://www.luogu.com.cn/contest/list"
option = webdriver.EdgeOptions()
option.add_experimental_option('excludeSwitches', ['enable-logging'])
option.add_argument('-disable-gpu')
option.add_argument('log-level=3')

CF_URL = "https://codeforces.com/contests?complete=true"

ATCODER_URL = "https://atcoder.jp"
Matches = []


def getLuoguMatches(url = LUOGU_URL):
    lgOption = copy.deepcopy(option)
    lgOption.add_argument("--headless")
    driver = webdriver.Edge(options=lgOption)
    driver.get(url)
    tree = BeautifulSoup(driver.page_source, "html.parser")
    try:
        match = tree.find_all("div", class_="row-wrap")[0]
        originalMatches = match.contents
    except:
        return
    for i in originalMatches:
        if "未开始" in str(i) or "进行中" in str(i):
            name = str(i.a.contents[0]).replace("\n", "").strip()
            startTime = str(i.contents[6].time.contents[0])
            endTime = str(i.contents[6].contents[2].contents[0])
            
            month = int(startTime.split(" ")[0].split("-")[0])
            day = int(startTime.split(" ")[0].split("-")[1])
            startHour = int(startTime.split(" ")[1].split(":")[0])
            startMinute = int(startTime.split(" ")[1].split(":")[1])
            endHour = int(endTime.split(":")[0])
            endMinute = int(endTime.split(":")[1])

            mat = Match(name, "Luogu", datetime(year=2025, month=month, day=day, hour=startHour, minute=startMinute, second=0),
                        endTime=datetime(year=2025, month=month, day=day, hour=endHour, minute=endMinute, second=0))
            Matches.append(mat)


def getCFMatches(url = CF_URL):
    driver = webdriver.Edge(options=option)
    driver.get(url)
    driver.minimize_window()
    ele = WebDriverWait(driver, 60).until(
        EC.presence_of_element_located((By.TAG_NAME, 'body'))
    )
    tree = BeautifulSoup(driver.page_source, "html.parser")
    try:
        match = tree.find_all("table")[0].contents[1].contents
    except:
        return

    for i in match:
        try:
            name = i.td.contents[0].text
            name = name.replace("\n", "").replace("\r", "")
            startTime = str(i.contents[5].contents[1].contents[0]) \
                .replace("\n", "").replace("\r", "").strip()
            lastsTime = str(i.contents[7].contents[0]).replace("\n", "") \
                .replace("\r", "").replace(" ", "")
            for mon in CALENDER.keys():
                startTime = startTime.replace(mon, CALENDER[mon])

            startDatetime = datetime.strptime(startTime, r"%m/%d/%Y %H:%M") + timedelta(hours=5)
            lasts = timedelta(hours=int(lastsTime.split(":")[0]), minutes=int(lastsTime.split(":")[1]))
            endDatetime = startDatetime + lasts
            mat = Match(name, "Codeforces", startDatetime, lastsTime=lasts, endTime=endDatetime)
            Matches.append(mat)
        except:
            continue


def getAtCoderMatches(url = ATCODER_URL):
    part: int = 1
    try:
        response = requests.get(url).content
        if (response.find(b"Active Contests")) != -1:
            part = 2
        tree = BeautifulSoup(response, "html.parser")
        match = []
        for i in range(part):
            match += tree.find_all("tbody")[i].contents
    except:
        return
    for i in match:
        try:
            name = str(i.contents[3].contents[0].a.contents[0])
            startTime = str(i.contents[1].contents[0].a.time.contents[0])
            startTime = startTime.split("+")[0]

            matchUrl = i.contents[3].contents[0].a["href"]
            specificInfoTree = BeautifulSoup(requests.get(url + matchUrl).content, "html.parser")
            div = specificInfoTree.find_all(id="contest-nav-tabs")[0]
            endDatetimeString = str(div.contents[1].small.contents[3].time.contents[0])
            endDateString = endDatetimeString.split(" ")[0].split("(")[0]
            endTimeString = endDatetimeString.split(" ")[1].split("+")[0]
            endDatetime = datetime.strptime(f"{endDateString} {endTimeString}", r"%Y-%m-%d %H:%M:%S")
            endDatetime -= timedelta(hours=1)
            
            mat = Match(name, "AtCoder", startTime=datetime.strptime(startTime, r"%Y-%m-%d %H:%M:%S") - timedelta(hours=1),
                        endTime=endDatetime)
            Matches.append(mat)
        except:
            continue


if __name__ == "__main__":
    t1 = threading.Thread(target=getLuoguMatches)
    t2 = threading.Thread(target=getCFMatches)
    t3 = threading.Thread(target=getAtCoderMatches)
    t1.start()
    t2.start()
    t3.start()

    t1.join()
    t2.join()
    t3.join()

    print("===============================Luogu===============================")
    for match in Matches:
        if match.platForm == 'Luogu':
            print(match)
    print("===============================Codeforces===============================")
    for match in Matches:
        if match.platForm == 'Codeforces':
            print(match)
    print("===============================AtCoder===============================")
    for match in Matches:
        if match.platForm == 'AtCoder':
            print(match)
    print("\n===============================All===============================")
    Matches.sort(key=lambda x: x.startTime)
    for match in Matches:
        print(match)
